from flask import Flask, render_template, request, redirect, url_for, session, flash, jsonify, send_file
import sqlite3
from werkzeug.security import generate_password_hash, check_password_hash
import os
import pandas as pd
import json
import random
import matplotlib.pyplot as plt
import matplotlib
matplotlib.use('Agg')  # 使用非交互式后端
import io
import base64
from datetime import datetime, timedelta
import numpy as np
from flask import Flask, render_template, request, redirect, url_for, session, flash

app = Flask(__name__)
app.secret_key = 'your_secret_key'  # 可自行修改

# ---------- 数据库初始化 ----------
def init_db():
    conn = sqlite3.connect('users.db')
    c = conn.cursor()
    c.execute('''
        CREATE TABLE IF NOT EXISTS users (
            id INTEGER PRIMARY KEY AUTOINCREMENT,
            username TEXT UNIQUE NOT NULL,
            password TEXT NOT NULL,
            role TEXT NOT NULL DEFAULT 'user'
        )
    ''')
    conn.commit()
    conn.close()

# ---------- 首页 ----------
@app.route('/')
def index():
    return render_template('home.html')

# ---------- 注册 ----------
@app.route('/register', methods=['GET', 'POST'])
def register():
    if request.method == 'POST':
        username = request.form['username']
        password = generate_password_hash(request.form['password'])
        role = request.form['role']
        try:
            conn = sqlite3.connect('users.db')
            c = conn.cursor()
            c.execute('INSERT INTO users (username, password, role) VALUES (?, ?, ?)', (username, password, role))
            conn.commit()
            flash("注册成功，请登录", "success")
            return redirect(url_for('login'))
        except sqlite3.IntegrityError:
            flash("用户名已存在", "danger")
        finally:
            conn.close()
    return render_template('register.html')

# ---------- 登录 ----------
@app.route('/login', methods=['GET', 'POST'])
def login():
    if request.method == 'POST':
        username = request.form['username']
        password_input = request.form['password']
        conn = sqlite3.connect('users.db')
        c = conn.cursor()
        c.execute('SELECT * FROM users WHERE username=?', (username,))
        user = c.fetchone()
        conn.close()
        if user and check_password_hash(user[2], password_input):
            session['username'] = username
            session['role'] = user[3]
            flash("登录成功", "success")
            if user[3] == 'admin':
                return redirect(url_for('admin_home'))
            elif user[3] == 'farmer':
                return redirect(url_for('farmer_home'))
            else:
                return redirect(url_for('user_home'))
        else:
            flash("用户名或密码错误", "danger")
    return render_template('login.html')

# ---------- 用户主页 ----------

# 设置文件上传路径
app.config['UPLOAD_FOLDER'] = 'uploads'
app.config['ALLOWED_EXTENSIONS'] = {'csv'}

# 确保上传文件夹存在
if not os.path.exists(app.config['UPLOAD_FOLDER']):
    os.makedirs(app.config['UPLOAD_FOLDER'])
    print(f"创建上传文件夹: {app.config['UPLOAD_FOLDER']}")

# 检查文件类型是否为 CSV
def allowed_file(filename):
    return '.' in filename and filename.rsplit('.', 1)[1].lower() in app.config['ALLOWED_EXTENSIONS']

# 路由：文件上传
@app.route('/upload', methods=['GET', 'POST'])
def upload_file():
    if 'username' not in session:
        return redirect(url_for('login'))
    
    if request.method == 'POST':
        # 检查是否有文件
        if 'file' not in request.files:
            flash('没有选择文件', 'danger')
            return redirect(request.url)
        
        file = request.files['file']
        
        # 检查文件名是否为空
        if file.filename == '':
            flash('没有选择文件', 'danger')
            return redirect(request.url)
        
        # 检查文件类型
        if file and allowed_file(file.filename):
            try:
                # 安全地保存文件
                filename = file.filename
                file_path = os.path.join(app.config['UPLOAD_FOLDER'], filename)
                file.save(file_path)
                
                # 读取并处理 CSV 文件内容
                data = pd.read_csv(file_path)
                print(f"数据读取成功，共 {len(data)} 行数据：")
                print(data.head())
                
                # 提取数据
                extracted_data = {}
                
                # 检查并提取温度数据
                if 'temperature' in data.columns:
                    extracted_data['temperature'] = round(data['temperature'].mean(), 1)
                    print(f"温度数据: {extracted_data['temperature']}℃")
                
                # 检查并提取pH数据
                if 'ph' in data.columns:
                    extracted_data['ph_value'] = round(data['ph'].mean(), 2)
                    print(f"pH数据: {extracted_data['ph_value']}")
                
                # 检查并提取溶解氧数据
                if 'dissolved_oxygen' in data.columns:
                    extracted_data['dissolved_oxygen'] = round(data['dissolved_oxygen'].mean(), 2)
                    print(f"溶解氧数据: {extracted_data['dissolved_oxygen']}mg/L")
                
                # 检查并提取鱼群数量数据
                if 'fish_count' in data.columns:
                    extracted_data['fish_count'] = int(data['fish_count'].sum())
                    print(f"鱼群数量: {extracted_data['fish_count']} 条")
                
                # 保存提取的数据到session中，供用户主页使用
                session['uploaded_data'] = extracted_data
                
                flash(f'文件 {filename} 上传成功！已提取 {len(extracted_data)} 项数据', 'success')
                return redirect(url_for('user_home'))
                
            except Exception as e:
                print(f"文件处理错误: {e}")
                flash(f'文件处理失败: {str(e)}', 'danger')
                return redirect(request.url)
        else:
            flash('请选择正确的CSV文件（.csv格式）', 'danger')
            return redirect(request.url)
    
    return render_template('upload.html')

# 主页显示数据
@app.route('/user_home')
def user_home():
    if 'username' not in session:
        return redirect(url_for('login'))
    
    # 读取鱼类数据
    try:
        fish_data = pd.read_csv('Fish.csv')
        fish_count = len(fish_data)  # 鱼类总数
        # 计算平均体重
        avg_weight = fish_data['Weight(g)'].mean()
        # 计算平均体长
        avg_length = fish_data['Length1(cm)'].mean()
    except Exception as e:
        print(f"读取鱼类数据出错: {e}")
        fish_count = 0
        avg_weight = 0
        avg_length = 0
    
    # 检查是否有上传的数据
    uploaded_data = session.get('uploaded_data', {})
    
    # 使用上传的数据，如果没有则使用模拟数据
    temperature = uploaded_data.get('temperature', round(random.uniform(15, 25), 1))
    ph_value = uploaded_data.get('ph_value', round(random.uniform(6.5, 8.5), 2))
    dissolved_oxygen = uploaded_data.get('dissolved_oxygen', round(random.uniform(6, 12), 2))
    uploaded_fish_count = uploaded_data.get('fish_count', fish_count)
    
    # 模拟气候数据
    average_temperature = round(random.uniform(18, 28), 1)  # 气温 18-28℃
    wind_speed = round(random.uniform(0, 10), 1)  # 风速 0-10 m/s
    
    return render_template('user_home.html', 
                         temperature=temperature,
                         ph_value=ph_value,
                         dissolved_oxygen=dissolved_oxygen,
                         fish_count=uploaded_fish_count,
                         average_temperature=average_temperature,
                         wind_speed=wind_speed,
                         avg_weight=avg_weight,
                         avg_length=avg_length,
                         has_uploaded_data=bool(uploaded_data))

# ---------- 水下系统 ----------
@app.route('/underwater')
def underwater_system():
    # 简单的数据生成器
    import random
    data = {
        'environment': {
            'temperature': round(random.uniform(15, 25), 1),
            'ph': round(random.uniform(6.5, 8.5), 2),
            'dissolved_oxygen': round(random.uniform(6, 12), 2),
            'turbidity': round(random.uniform(0, 50), 1)
        }
    }
    return render_template('underwater.html', data=data)

# ---------- 数据中心 ----------
@app.route('/data_center')
def data_center():
    # 简单的数据生成器
    import random
    data = {
        'water_quality': {
            'temperature': round(random.uniform(15, 25), 1),
            'ph': round(random.uniform(6.5, 8.5), 2),
            'dissolved_oxygen': round(random.uniform(6, 12), 2)
        },
        'fish_data': {
            'count': random.randint(100, 500),
            'species': ['鲤鱼', '草鱼', '鲢鱼', '鳙鱼']
        }
    }
    return render_template('data_center.html', data=data)

# ---------- 智能中心 ----------
@app.route('/intelligence')
def intelligence_center():
    # 简单的环境数据生成
    import random
    env_data = {
        'temperature': round(random.uniform(15, 25), 1),
        'ph': round(random.uniform(6.5, 8.5), 2),
        'dissolved_oxygen': round(random.uniform(6, 12), 2)
    }
    
    # 简单的环境评分计算
    score = 85 + random.randint(-10, 10)  # 75-95分
    score = max(0, min(100, score))  # 确保在0-100范围内
    
    return render_template('intelligence.html', env_score=score, env_data=env_data)

# ---------- 管理员主页 ----------
@app.route('/admin_home')
def admin_home():
    if session.get('role') != 'admin':
        return "无权限", 403
    conn = sqlite3.connect('users.db')
    c = conn.cursor()
    c.execute("SELECT id, username, role FROM users")
    users = c.fetchall()
    conn.close()
    return render_template('manage_users.html', users=users)

# 用户管理（仅管理员可访问）
@app.route('/admin/users')
def manage_users():
    if session.get('role') != 'admin':
        return "无权限", 403
    conn = sqlite3.connect('users.db')
    c = conn.cursor()
    c.execute("SELECT id, username, role FROM users")
    users = c.fetchall()
    conn.close()
    return render_template('manage_users.html', users=users)

# 删除用户（仅管理员可操作，禁止删除管理员）
@app.route('/admin/delete_user/<int:user_id>')
def delete_user(user_id):
    if session.get('role') != 'admin':
        return "无权限", 403
    conn = sqlite3.connect('users.db')
    c = conn.cursor()
    c.execute("SELECT role FROM users WHERE id = ?", (user_id,))
    role = c.fetchone()
    if role and role[0] != 'admin':
        c.execute("DELETE FROM users WHERE id = ?", (user_id,))
        conn.commit()
    conn.close()
    return redirect(url_for('manage_users'))


@app.route('/farmer_home')
def farmer_home():
    if session.get('role') != 'farmer':
        flash("无权限访问养殖户页面", "danger")
        return redirect(url_for('index'))
    return render_template('farmer_home.html')


# ---------- 退出登录 ----------
@app.route('/logout')
def logout():
    session.clear()
    flash("您已退出", "info")
    return redirect(url_for('login'))

# ---------- 数据处理与分析模块 ----------

# 数据可视化路由
@app.route('/data_visualization')
def data_visualization():
    if 'username' not in session:
        return redirect(url_for('login'))
    
    # 读取鱼类数据
    try:
        fish_data = pd.read_csv('Fish.csv')
        
        # 生成图表数据
        species_counts = fish_data['Species'].value_counts()
        weight_stats = fish_data.groupby('Species')['Weight(g)'].mean()
        length_stats = fish_data.groupby('Species')['Length1(cm)'].mean()
        
        # 生成图表
        fig, ((ax1, ax2), (ax3, ax4)) = plt.subplots(2, 2, figsize=(12, 10))
        
        # 鱼类种类分布饼图
        ax1.pie(species_counts.values, labels=species_counts.index, autopct='%1.1f%%')
        ax1.set_title('鱼类种类分布')
        
        # 体重分布柱状图
        weight_stats.plot(kind='bar', ax=ax2, color='skyblue')
        ax2.set_title('各品种平均体重')
        ax2.set_ylabel('体重 (g)')
        ax2.tick_params(axis='x', rotation=45)
        
        # 体长分布柱状图
        length_stats.plot(kind='bar', ax=ax3, color='lightgreen')
        ax3.set_title('各品种平均体长')
        ax3.set_ylabel('体长 (cm)')
        ax3.tick_params(axis='x', rotation=45)
        
        # 体重vs体长散点图
        ax4.scatter(fish_data['Length1(cm)'], fish_data['Weight(g)'], alpha=0.6)
        ax4.set_xlabel('体长 (cm)')
        ax4.set_ylabel('体重 (g)')
        ax4.set_title('体重vs体长关系')
        
        plt.tight_layout()
        
        # 将图表转换为base64字符串
        img_buffer = io.BytesIO()
        plt.savefig(img_buffer, format='png', dpi=300, bbox_inches='tight')
        img_buffer.seek(0)
        img_str = base64.b64encode(img_buffer.getvalue()).decode()
        plt.close()
        
        return render_template('data_visualization.html', 
                             chart_data=img_str,
                             species_data=species_counts.to_dict(),
                             weight_data=weight_stats.to_dict(),
                             length_data=length_stats.to_dict())
    except Exception as e:
        flash(f"数据可视化出错: {e}", "danger")
        return redirect(url_for('user_home'))

# 数据导出路由
@app.route('/export_data')
def export_data():
    if 'username' not in session:
        return redirect(url_for('login'))
    
    try:
        fish_data = pd.read_csv('Fish.csv')
        
        # 创建Excel文件
        output = io.BytesIO()
        with pd.ExcelWriter(output, engine='openpyxl') as writer:
            fish_data.to_excel(writer, sheet_name='鱼类数据', index=False)
            
            # 添加统计信息
            stats_data = {
                '统计项目': ['总数量', '平均体重', '平均体长', '最大体重', '最小体重'],
                '数值': [
                    len(fish_data),
                    round(fish_data['Weight(g)'].mean(), 2),
                    round(fish_data['Length1(cm)'].mean(), 2),
                    fish_data['Weight(g)'].max(),
                    fish_data['Weight(g)'].min()
                ]
            }
            pd.DataFrame(stats_data).to_excel(writer, sheet_name='统计信息', index=False)
        
        output.seek(0)
        return send_file(
            output,
            mimetype='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
            as_attachment=True,
            download_name=f'鱼类数据_{datetime.now().strftime("%Y%m%d_%H%M%S")}.xlsx'
        )
    except Exception as e:
        flash(f"数据导出出错: {e}", "danger")
        return redirect(url_for('user_home'))

# 图表下载路由
@app.route('/download_chart/<chart_type>')
def download_chart(chart_type):
    if 'username' not in session:
        return redirect(url_for('login'))
    
    try:
        fish_data = pd.read_csv('Fish.csv')
        
        if chart_type == 'species_distribution':
            # 鱼类种类分布饼图
            species_counts = fish_data['Species'].value_counts()
            plt.figure(figsize=(10, 8))
            plt.pie(species_counts.values, labels=species_counts.index, autopct='%1.1f%%')
            plt.title('鱼类种类分布')
            
        elif chart_type == 'weight_analysis':
            # 体重分析
            weight_stats = fish_data.groupby('Species')['Weight(g)'].mean()
            plt.figure(figsize=(10, 6))
            weight_stats.plot(kind='bar', color='skyblue')
            plt.title('各品种平均体重')
            plt.ylabel('体重 (g)')
            plt.xticks(rotation=45)
            
        elif chart_type == 'length_analysis':
            # 体长分析
            length_stats = fish_data.groupby('Species')['Length1(cm)'].mean()
            plt.figure(figsize=(10, 6))
            length_stats.plot(kind='bar', color='lightgreen')
            plt.title('各品种平均体长')
            plt.ylabel('体长 (cm)')
            plt.xticks(rotation=45)
            
        elif chart_type == 'weight_length_correlation':
            # 体重vs体长散点图
            plt.figure(figsize=(10, 6))
            plt.scatter(fish_data['Length1(cm)'], fish_data['Weight(g)'], alpha=0.6)
            plt.xlabel('体长 (cm)')
            plt.ylabel('体重 (g)')
            plt.title('体重vs体长关系')
            
        plt.tight_layout()
        
        # 保存图表
        img_buffer = io.BytesIO()
        plt.savefig(img_buffer, format='png', dpi=300, bbox_inches='tight')
        img_buffer.seek(0)
        plt.close()
        
        return send_file(
            img_buffer,
            mimetype='image/png',
            as_attachment=True,
            download_name=f'{chart_type}_{datetime.now().strftime("%Y%m%d_%H%M%S")}.png'
        )
    except Exception as e:
        flash(f"图表下载出错: {e}", "danger")
        return redirect(url_for('data_visualization'))

# 实时数据API
@app.route('/api/realtime_data')
def realtime_data():
    if 'username' not in session:
        return jsonify({'error': '未登录'}), 401
    
    # 模拟实时数据
    data = {
        'timestamp': datetime.now().isoformat(),
        'water_quality': {
            'temperature': round(random.uniform(15, 25), 1),
            'ph': round(random.uniform(6.5, 8.5), 2),
            'dissolved_oxygen': round(random.uniform(6, 12), 2),
            'turbidity': round(random.uniform(0, 50), 1)
        },
        'fish_count': random.randint(100, 500),
        'system_status': 'normal'
    }
    
    return jsonify(data)

# ---------- 报警与通知模块 ----------

# 全局数据管理器
class GlobalDataManager:
    def __init__(self):
        self.alarm_records = []
        self._init_test_data()
    
    def _init_test_data(self):
        """初始化测试数据"""
        if not self.alarm_records:
            test_alarms = [
                {
                    'timestamp': datetime.now().strftime('%Y-%m-%d %H:%M:%S'),
                    'type': 'temperature',
                    'value': 28.5,
                    'threshold': {'min': 15, 'max': 25},
                    'message': '水温异常: 28.5℃ (正常范围: 15-25℃)',
                    'severity': 'high'
                },
                {
                    'timestamp': datetime.now().strftime('%Y-%m-%d %H:%M:%S'),
                    'type': 'ph',
                    'value': 5.8,
                    'threshold': {'min': 6.5, 'max': 8.5},
                    'message': 'pH值异常: 5.8 (正常范围: 6.5-8.5)',
                    'severity': 'medium'
                }
            ]
            self.alarm_records.extend(test_alarms)
            print(f"初始化报警系统，添加了 {len(test_alarms)} 条测试记录")
    
    def add_alarm(self, alarm):
        """添加报警记录"""
        self.alarm_records.append(alarm)
        print(f"添加报警记录: {alarm}")
    
    def get_alarms(self, limit=50):
        """获取报警记录"""
        return self.alarm_records[-limit:]
    
    def clear_alarms(self):
        """清除所有报警记录"""
        self.alarm_records.clear()
        print("清除所有报警记录")

# 创建全局实例
global_data = GlobalDataManager()

# 报警记录存储
alarm_records = global_data.alarm_records

# 报警阈值设置
ALARM_THRESHOLDS = {
    'temperature': {'min': 15, 'max': 25},
    'ph': {'min': 6.5, 'max': 8.5},
    'dissolved_oxygen': {'min': 6, 'max': 12},
    'turbidity': {'min': 0, 'max': 50}
}

# 报警设置页面
@app.route('/alarm_settings', methods=['GET', 'POST'])
def alarm_settings():
    if 'username' not in session:
        return redirect(url_for('login'))
    
    # 只在没有报警记录时才初始化测试数据
    if not global_data.alarm_records:
        global_data._init_test_data()
    
    if request.method == 'POST':
        # 更新报警阈值
        ALARM_THRESHOLDS['temperature']['min'] = float(request.form['min_temp'])
        ALARM_THRESHOLDS['temperature']['max'] = float(request.form['max_temp'])
        ALARM_THRESHOLDS['ph']['min'] = float(request.form['min_ph'])
        ALARM_THRESHOLDS['ph']['max'] = float(request.form['max_ph'])
        ALARM_THRESHOLDS['dissolved_oxygen']['min'] = float(request.form['min_do'])
        ALARM_THRESHOLDS['dissolved_oxygen']['max'] = float(request.form['max_do'])
        
        flash("报警阈值设置已保存", "success")
        return redirect(url_for('alarm_settings'))
    
    return render_template('alarm_settings.html', thresholds=ALARM_THRESHOLDS)

# 报警记录页面
@app.route('/alarm_records')
def alarm_records():
    if 'username' not in session:
        return redirect(url_for('login'))
    
    # 只在没有报警记录时才初始化测试数据
    if not global_data.alarm_records:
        global_data._init_test_data()
    
    print(f"报警记录页面显示 {len(global_data.alarm_records)} 条记录")
    return render_template('alarm_records.html', alarms=global_data.get_alarms())

# 检查数据异常并生成报警
def check_alarms(data):
    alarms = []
    
    # 检查水温
    if data.get('temperature'):
        temp = data['temperature']
        if temp < ALARM_THRESHOLDS['temperature']['min'] or temp > ALARM_THRESHOLDS['temperature']['max']:
            alarm = {
                'timestamp': datetime.now().strftime('%Y-%m-%d %H:%M:%S'),
                'type': 'temperature',
                'value': temp,
                'threshold': ALARM_THRESHOLDS['temperature'],
                'message': f'水温异常: {temp}℃ (正常范围: {ALARM_THRESHOLDS["temperature"]["min"]}-{ALARM_THRESHOLDS["temperature"]["max"]}℃)',
                'severity': 'high' if abs(temp - 20) > 5 else 'medium'
            }
            alarms.append(alarm)
    
    # 检查pH值
    if data.get('ph'):
        ph = data['ph']
        if ph < ALARM_THRESHOLDS['ph']['min'] or ph > ALARM_THRESHOLDS['ph']['max']:
            alarm = {
                'timestamp': datetime.now().strftime('%Y-%m-%d %H:%M:%S'),
                'type': 'ph',
                'value': ph,
                'threshold': ALARM_THRESHOLDS['ph'],
                'message': f'pH值异常: {ph} (正常范围: {ALARM_THRESHOLDS["ph"]["min"]}-{ALARM_THRESHOLDS["ph"]["max"]})',
                'severity': 'high' if ph < 6.0 or ph > 9.0 else 'medium'
            }
            alarms.append(alarm)
    
    # 检查溶解氧
    if data.get('dissolved_oxygen'):
        do = data['dissolved_oxygen']
        if do < ALARM_THRESHOLDS['dissolved_oxygen']['min'] or do > ALARM_THRESHOLDS['dissolved_oxygen']['max']:
            alarm = {
                'timestamp': datetime.now().strftime('%Y-%m-%d %H:%M:%S'),
                'type': 'dissolved_oxygen',
                'value': do,
                'threshold': ALARM_THRESHOLDS['dissolved_oxygen'],
                'message': f'溶解氧异常: {do}mg/L (正常范围: {ALARM_THRESHOLDS["dissolved_oxygen"]["min"]}-{ALARM_THRESHOLDS["dissolved_oxygen"]["max"]}mg/L)',
                'severity': 'high' if do < 4 else 'medium'
            }
            alarms.append(alarm)
    
    # 将报警记录添加到全局列表
    for alarm in alarms:
        global_data.add_alarm(alarm)
    
    return alarms

# 报警API
@app.route('/api/check_alarms')
def api_check_alarms():
    try:
        if 'username' not in session:
            return jsonify({'error': '未登录'}), 401
        
        print("开始处理报警API请求")  # 调试信息
        
        # 确保报警系统已初始化
        global_data._init_test_data()
        
        # 获取当前数据
        current_data = {
            'temperature': round(random.uniform(15, 25), 1),
            'ph': round(random.uniform(6.5, 8.5), 2),
            'dissolved_oxygen': round(random.uniform(6, 12), 2),
            'turbidity': round(random.uniform(0, 50), 1)
        }
        
        print(f"当前数据: {current_data}")  # 调试信息
        
        # 简化报警检查，避免复杂的逻辑
        alarms = []
        
        # 检查水温
        temp = current_data['temperature']
        if temp < 15 or temp > 25:
            alarm = {
                'timestamp': datetime.now().strftime('%Y-%m-%d %H:%M:%S'),
                'type': 'temperature',
                'value': temp,
                'threshold': {'min': 15, 'max': 25},
                'message': f'水温异常: {temp}℃ (正常范围: 15-25℃)',
                'severity': 'high' if abs(temp - 20) > 5 else 'medium'
            }
            alarms.append(alarm)
        
        # 检查pH值
        ph = current_data['ph']
        if ph < 6.5 or ph > 8.5:
            alarm = {
                'timestamp': datetime.now().strftime('%Y-%m-%d %H:%M:%S'),
                'type': 'ph',
                'value': ph,
                'threshold': {'min': 6.5, 'max': 8.5},
                'message': f'pH值异常: {ph} (正常范围: 6.5-8.5)',
                'severity': 'high' if ph < 6.0 or ph > 9.0 else 'medium'
            }
            alarms.append(alarm)
        
        # 检查溶解氧
        do = current_data['dissolved_oxygen']
        if do < 6 or do > 12:
            alarm = {
                'timestamp': datetime.now().strftime('%Y-%m-%d %H:%M:%S'),
                'type': 'dissolved_oxygen',
                'value': do,
                'threshold': {'min': 6, 'max': 12},
                'message': f'溶解氧异常: {do}mg/L (正常范围: 6-12mg/L)',
                'severity': 'high' if do < 4 else 'medium'
            }
            alarms.append(alarm)
        
        # 将报警添加到全局列表
        for alarm in alarms:
            global_data.add_alarm(alarm)
        
        print(f"生成的报警: {alarms}")  # 调试信息
        print(f"全局报警记录数量: {len(global_data.alarm_records)}")  # 调试信息
        
        response_data = {
            'current_data': current_data,
            'alarms': alarms,
            'alarm_count': len(alarms)
        }
        
        print(f"报警API响应: {response_data}")  # 调试信息
        return jsonify(response_data)
        
    except Exception as e:
        import traceback
        print(f"报警API错误: {e}")  # 调试信息
        print(f"错误详情: {traceback.format_exc()}")  # 详细错误信息
        return jsonify({
            'error': '服务器内部错误',
            'message': str(e)
        }), 500

# 清除报警记录
@app.route('/clear_alarms', methods=['POST'])
def clear_alarms():
    if 'username' not in session:
        return redirect(url_for('login'))
    
    global_data.clear_alarms()
    flash("报警记录已清除", "success")
    return redirect(url_for('alarm_records'))

# ---------- 智能化模块 ----------

# 鱼类体长预测模型（简单线性回归）
def predict_fish_length(weight, species='Bream'):
    """基于体重预测鱼类体长"""
    try:
        fish_data = pd.read_csv('Fish.csv')
        species_data = fish_data[fish_data['Species'] == species]
        
        if len(species_data) < 2:
            return None
        
        # 简单线性回归
        X = species_data['Weight(g)'].values.reshape(-1, 1)
        y = species_data['Length1(cm)'].values
        
        from sklearn.linear_model import LinearRegression
        model = LinearRegression()
        model.fit(X, y)
        
        predicted_length = model.predict([[weight]])[0]
        return round(predicted_length, 2)
    except Exception as e:
        print(f"体长预测出错: {e}")
        return None

# 智能问答系统
def get_ai_answer(question):
    """简单的智能问答系统"""
    question = question.lower()
    
    # 预设问答对
    qa_pairs = {
        '水温': '水温是影响鱼类生长的重要因素，适宜的水温范围通常在15-25℃之间。',
        'ph': 'pH值反映水体的酸碱度，鱼类适宜的pH值范围通常在6.5-8.5之间。',
        '溶解氧': '溶解氧是鱼类呼吸必需的，正常范围应在6-12mg/L之间。',
        '喂食': '鱼类喂食应根据水温、鱼种和生长阶段调整，一般每天1-2次。',
        '疾病': '常见鱼类疾病包括白点病、烂鳃病等，需要及时隔离治疗。',
        '水质': '良好的水质是鱼类健康生长的关键，需要定期监测和调节。',
        '温度': '水温变化会影响鱼类的代谢和食欲，需要保持稳定。',
        '氧气': '充足的溶解氧是鱼类生存的基本条件。',
        '饲料': '优质饲料应含有足够的蛋白质、脂肪和维生素。',
        '养殖': '科学养殖需要综合考虑水质、饲料、密度等多个因素。'
    }
    
    # 关键词匹配
    for keyword, answer in qa_pairs.items():
        if keyword in question:
            return answer
    
    # 默认回答
    return "抱歉，我暂时无法回答这个问题。请尝试询问关于水温、pH值、溶解氧、喂食、疾病、水质、温度、氧气、饲料或养殖方面的问题。"

# 图片识别功能（模拟）
def identify_fish_species(image_data):
    """模拟鱼类图片识别"""
    # 这里应该集成真实的图像识别模型
    # 目前返回模拟结果
    species_list = ['Bream', 'Roach', 'Whitefish', 'Parkki', 'Perch', 'Pike', 'Smelt']
    confidence = random.uniform(0.7, 0.95)
    
    return {
        'species': random.choice(species_list),
        'confidence': round(confidence, 3),
        'message': f'识别结果：{random.choice(species_list)}，置信度：{round(confidence, 3)}'
    }

# 智能问答路由
@app.route('/ai_chat', methods=['GET', 'POST'])
def ai_chat():
    if 'username' not in session:
        return redirect(url_for('login'))
    
    if request.method == 'POST':
        question = request.form.get('question', '')
        if question:
            answer = get_ai_answer(question)
            return jsonify({'answer': answer})
    
    return render_template('ai_chat.html')

# 鱼类体长预测路由
@app.route('/fish_prediction', methods=['GET', 'POST'])
def fish_prediction():
    if 'username' not in session:
        return redirect(url_for('login'))
    
    if request.method == 'POST':
        try:
            weight = float(request.form['weight'])
            species = request.form.get('species', 'Bream')
            
            predicted_length = predict_fish_length(weight, species)
            
            if predicted_length:
                result = {
                    'weight': weight,
                    'species': species,
                    'predicted_length': predicted_length,
                    'message': f'预测体长：{predicted_length}cm'
                }
            else:
                result = {
                    'error': '预测失败，请检查输入数据'
                }
            
            return jsonify(result)
        except ValueError:
            return jsonify({'error': '请输入有效的体重数值'})
    
    return render_template('fish_prediction.html')

# 图片识别路由
@app.route('/image_recognition', methods=['GET', 'POST'])
def image_recognition():
    if 'username' not in session:
        return redirect(url_for('login'))
    
    if request.method == 'POST':
        if 'image' in request.files:
            file = request.files['image']
            if file and file.filename:
                # 模拟图片识别
                result = identify_fish_species(file.read())
                return jsonify(result)
    
    return render_template('image_recognition.html')

# 智能分析路由
@app.route('/smart_analysis')
def smart_analysis():
    if 'username' not in session:
        return redirect(url_for('login'))
    
    try:
        fish_data = pd.read_csv('Fish.csv')
        
        # 智能分析结果
        analysis_results = {
            'total_fish': len(fish_data),
            'species_count': len(fish_data['Species'].unique()),
            'avg_weight': round(fish_data['Weight(g)'].mean(), 2),
            'avg_length': round(fish_data['Length1(cm)'].mean(), 2),
            'largest_fish': fish_data.loc[fish_data['Weight(g)'].idxmax()].to_dict(),
            'health_score': round(random.uniform(75, 95), 1),
            'recommendations': [
                '建议定期监测水质参数',
                '注意控制养殖密度',
                '合理投喂优质饲料',
                '保持水体清洁'
            ]
        }
        
        return render_template('smart_analysis.html', analysis=analysis_results)
    except Exception as e:
        flash(f"智能分析出错: {e}", "danger")
        return redirect(url_for('user_home'))

# 鱼类运动轨迹追踪
def generate_fish_trajectory(fish_id, duration_hours=24):
    """生成鱼类运动轨迹数据"""
    import random
    from datetime import datetime, timedelta
    
    trajectory = []
    start_time = datetime.now() - timedelta(hours=duration_hours)
    
    # 模拟运动轨迹（在100x100的区域内）
    x, y = random.uniform(10, 90), random.uniform(10, 90)
    
    for i in range(duration_hours * 12):  # 每5分钟一个数据点
        timestamp = start_time + timedelta(minutes=i*5)
        
        # 模拟鱼类游动（随机游动+趋向性）
        x += random.uniform(-2, 2)
        y += random.uniform(-2, 2)
        
        # 保持在边界内
        x = max(0, min(100, x))
        y = max(0, min(100, y))
        
        # 添加深度信息
        depth = random.uniform(1, 5)
        
        trajectory.append({
            'timestamp': timestamp.strftime('%Y-%m-%d %H:%M:%S'),
            'x': round(x, 2),
            'y': round(y, 2),
            'depth': round(depth, 2),
            'speed': round(random.uniform(0.1, 2.0), 2)
        })
    
    return trajectory

# 养殖建议生成系统
def generate_farming_advice(water_quality, fish_data, weather_data):
    """基于多维度数据生成养殖建议"""
    advice_list = []
    
    # 基于水质数据的建议
    if water_quality.get('temperature', 20) < 15:
        advice_list.append({
            'type': 'warning',
            'title': '水温偏低',
            'content': '当前水温偏低，建议适当提高水温或减少投喂量，避免鱼类应激。',
            'priority': 'high'
        })
    elif water_quality.get('temperature', 20) > 25:
        advice_list.append({
            'type': 'warning',
            'title': '水温偏高',
            'content': '当前水温偏高，建议增加水体流动，适当遮阳，注意观察鱼类活动。',
            'priority': 'high'
        })
    
    if water_quality.get('ph', 7.0) < 6.5:
        advice_list.append({
            'type': 'warning',
            'title': 'pH值偏低',
            'content': 'pH值偏低，建议添加石灰或碳酸氢钠调节水质。',
            'priority': 'medium'
        })
    elif water_quality.get('ph', 7.0) > 8.5:
        advice_list.append({
            'type': 'warning',
            'title': 'pH值偏高',
            'content': 'pH值偏高，建议适当换水或添加酸性物质调节。',
            'priority': 'medium'
        })
    
    if water_quality.get('dissolved_oxygen', 8) < 6:
        advice_list.append({
            'type': 'danger',
            'title': '溶解氧不足',
            'content': '溶解氧严重不足，立即开启增氧设备，减少投喂量。',
            'priority': 'critical'
        })
    
    # 基于鱼类数据的建议
    if fish_data.get('density', 0) > 80:
        advice_list.append({
            'type': 'warning',
            'title': '养殖密度过高',
            'content': '当前养殖密度较高，建议适当分池或减少投苗量。',
            'priority': 'medium'
        })
    
    # 基于天气数据的建议
    if weather_data.get('temperature', 20) > 30:
        advice_list.append({
            'type': 'info',
            'title': '高温天气',
            'content': '高温天气，建议增加换水频率，适当遮阳，注意防暑降温。',
            'priority': 'medium'
        })
    
    if weather_data.get('rain', False):
        advice_list.append({
            'type': 'info',
            'title': '雨天管理',
            'content': '雨天注意水质变化，适当减少投喂量，防止水质恶化。',
            'priority': 'low'
        })
    
    # 常规建议
    advice_list.append({
        'type': 'success',
        'title': '日常管理',
        'content': '建议定期监测水质参数，保持水体清洁，合理投喂优质饲料。',
        'priority': 'low'
    })
    
    return advice_list

# 鱼类运动轨迹追踪路由
@app.route('/fish_tracking')
def fish_tracking():
    if 'username' not in session:
        return redirect(url_for('login'))
    
    # 生成模拟轨迹数据
    trajectories = {}
    for i in range(5):  # 5条鱼的轨迹
        fish_id = f"fish_{i+1}"
        trajectories[fish_id] = generate_fish_trajectory(fish_id, 24)
    
    return render_template('fish_tracking.html', trajectories=trajectories)

# 养殖建议路由
@app.route('/farming_advice')
def farming_advice():
    if 'username' not in session:
        return redirect(url_for('login'))
    
    # 模拟当前数据
    water_quality = {
        'temperature': round(random.uniform(15, 25), 1),
        'ph': round(random.uniform(6.5, 8.5), 2),
        'dissolved_oxygen': round(random.uniform(6, 12), 2),
        'turbidity': round(random.uniform(0, 50), 1)
    }
    
    # 读取鱼类数据
    try:
        fish_data_csv = pd.read_csv('Fish.csv')
        fish_data = {
            'count': len(fish_data_csv),
            'avg_weight': fish_data_csv['Weight(g)'].mean(),
            'avg_length': fish_data_csv['Length1(cm)'].mean(),
            'density': random.randint(50, 100),
            'health_score': round(random.uniform(75, 95), 1),
            'feeding_rate': round(random.uniform(2, 5), 1)
        }
    except Exception as e:
        print(f"读取鱼类数据出错: {e}")
        fish_data = {
            'count': 0,
            'avg_weight': 0,
            'avg_length': 0,
            'density': random.randint(50, 100),
            'health_score': round(random.uniform(75, 95), 1),
            'feeding_rate': round(random.uniform(2, 5), 1)
        }
    
    weather_data = {
        'temperature': round(random.uniform(15, 35), 1),
        'humidity': random.randint(40, 90),
        'rain': random.choice([True, False]),
        'wind_speed': round(random.uniform(0, 15), 1)
    }
    
    # 生成建议
    advice_list = generate_farming_advice(water_quality, fish_data, weather_data)
    
    # 添加时间戳到建议中
    current_time = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
    for advice in advice_list:
        advice['timestamp'] = current_time
    
    return render_template('farming_advice.html', 
                         advice_list=advice_list,
                         water_quality=water_quality,
                         fish_data=fish_data,
                         weather_data=weather_data,
                         current_time=current_time)

# 轨迹数据API
@app.route('/api/trajectory/<fish_id>')
def api_trajectory(fish_id):
    if 'username' not in session:
        return jsonify({'error': '未登录'}), 401
    
    trajectory = generate_fish_trajectory(fish_id, 24)
    return jsonify({
        'fish_id': fish_id,
        'trajectory': trajectory
    })

# 建议生成API
@app.route('/api/generate_advice', methods=['POST'])
def api_generate_advice():
    if 'username' not in session:
        return jsonify({'error': '未登录'}), 401
    
    data = request.get_json()
    water_quality = data.get('water_quality', {})
    fish_data = data.get('fish_data', {})
    weather_data = data.get('weather_data', {})
    
    advice_list = generate_farming_advice(water_quality, fish_data, weather_data)
    return jsonify({'advice_list': advice_list})

# 测试API
@app.route('/api/test')
def api_test():
    return jsonify({
        'status': 'success',
        'message': 'API连接正常',
        'timestamp': datetime.now().isoformat()
    })

# ---------- 主程序启动 ----------
if __name__ == '__main__':
    init_db()
    app.run(debug=True)
